using System;

namespace Digitalmes.Common.Utils;

/// <summary>
/// String 帮助类。
/// </summary>
public static class StringUtils
{
    /// <summary>
    /// 校验字符串是否满足任意一个指定的匹配规则。
    /// </summary>
    /// <param name="value">要匹配的值</param>
    /// <param name="matchPatterns">匹配规则集合</param>
    /// <param name="placeholder">规则中的占位字符</param>
    /// <param name="isWholeMatched">是否完整匹配。非完整匹配时条码长度不能短于规则长度，完整匹配时两者长度需完全相等。</param>
    /// <returns>匹配规则集合为空时返回 true。</returns>
    public static bool Match(string value, IEnumerable<string> matchPatterns, char placeholder, bool isWholeMatched)
    {
        if (!matchPatterns.Any())
        {
            return true;
        }

        return matchPatterns.Any(rule => Match(value, rule, placeholder, isWholeMatched));
    }

    /// <summary>
    /// 校验字符串是否满足指定的匹配规则。
    /// </summary>
    /// <param name="value">要匹配的值</param>
    /// <param name="matchPattern">匹配规则</param>
    /// <param name="placeholder">规则中的占位字符</param>
    /// <param name="isWholeMatched">是否完整匹配。非完整匹配时条码长度不能短于规则长度，完整匹配时两者长度需完全相等。</param>
    /// <returns></returns>
    public static bool Match(string value, string matchPattern, char placeholder, bool isWholeMatched)
    {
        // 条码长度不能小于规则长度；若完整匹配时，条码长度需等于规则长度
        if (value.Length < matchPattern.Length || (isWholeMatched && value.Length != matchPattern.Length))
        {
            return false;
        }

        for (var i = 0; i < matchPattern.Length; i++)
        {
            if (matchPattern[i] != value[i] && matchPattern[i] != placeholder)
            {
                return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 从指定字符串中提取一段字符串。
    /// </summary>
    /// <param name="value">要提取的字符串</param>
    /// <param name="start">其实位置，从 0 开始</param>
    /// <param name="len">要提取的长度</param>
    /// <returns>当指定的起始位置和长度超出字符串长度时返回 false。</returns>
    public static (bool Ok, string? Substring) Extract(string value, int start, int len)
    {
        if (string.IsNullOrEmpty(value))
        {
            return (false, default);
        }

        if (start < 0 || start >= value.Length)
        {
            return (false, default);
        }

        if (len < 0 || start + len > value.Length)
        {
            return (false, default);
        }

        return (true, value.Substring(start, len));
    }

    /// <summary>
    /// 尝试从指定字符串中提取一段字符串。
    /// </summary>
    /// <param name="value">要提取的字符串</param>
    /// <param name="start">其实位置，从 0 开始</param>
    /// <param name="len">要提取的长度</param>
    /// <param name="subString">提取的字符串</param>
    /// <returns>当指定的起始位置和长度超出字符串长度时返回 false。</returns>
    public static bool TryExtract(string value, int start, int len, [NotNullWhen(true)] out string? subString)
    {
        var (ok, v2) = Extract(value, start, len);
        subString = v2;
        return ok;
    }

    /// <summary>
    /// 将字符串按分隔符分割并转换为 Int32 类型数值，若无法分割则返回 false。
    /// </summary>
    /// <param name="value"></param>
    /// <param name="separator">分隔符</param>
    /// <returns></returns>
    public static (bool, int D1, int D2) SplitToInt(string value, char separator)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return (false, default, default);
        }

        int i = 0, maxCount = 2;
        Span<Range> ranges = stackalloc Range[maxCount];
        foreach (var range in value.AsSpan().Split(separator))
        {
            // 索引不能超过上限
            if (i > maxCount - 1)
            {
                return (false, default, default);
            }

            ranges[i++] = range;
        }

        if (int.TryParse(value[ranges[0]], out var d1) && int.TryParse(value[ranges[1]], out var d2))
        {
            return (true, d1, d2);
        }

        return (false, default, default);
    }
}
